AddCSLuaFile( "cl_init.lua" )
AddCSLuaFile( "shared.lua" )
include('shared.lua')

include('entities/base_wire_entity/init.lua')
---------------------------------------------
-- Entity Functions
---------------------------------------------

function ENT:Initialize()
	self.Entity:SetModel("models/props_lab/reciever01b.mdl")
	self.Entity:PhysicsInit( SOLID_VPHYSICS )
	self.Entity:SetMoveType(MOVETYPE_VPHYSICS)
	self.Entity:SetSolid(SOLID_VPHYSICS)
	self.Entity:SetUseType(SIMPLE_USE)
	
	self.code = 0
	self.autoclose = false
	self.didclose = false	--Without this, the iris would close within a half second of opening.
	self.donotautoopen = false	--Open automatically when a correct code comes in?
	self.CodeStatus = 0
	self.closetime = 0
	self.wireCode = 0
	self.LockedGate = self.Entity
	self.LockedIris = self.Entity
	
	--wire stuff
	
	if not (WireAddon == nil) then 
		self.WireDebugName = self.PrintName
		self.Inputs = Wire_CreateInputs(self.Entity, { "Iris Control" })
		self.Outputs = Wire_CreateOutputs( self.Entity, { "Incoming Wormhole", "Code Status", "Gate Active", "Received Code" })	
	end
	
end

local function AutoClose(EntTable)	--timer function
	local gate, iris
	if EntTable.LockedGate == EntTable.Entity then
		gate, iris = EntTabble:FindGate()
	else
		gate, iris = EntTable.LockedGate, EntTable.LockedIris
	end
	if gate.IsOpen and not iris.IsActivated then
		iris:Toggle()
		EntTable.didclose = true
	end
	EntTable.wireCode = 0
	EntTable.CodeStatus = 0
end

function ENT:SpawnFunction( ply, tr)
	local SpawnPos = tr.HitPos + tr.HitNormal * 50
	local ent = ents.Create( "iris_computer" )
	ent:SetPos( SpawnPos )
	ent:Spawn()
	ent:Activate()
	return ent
end

function ENT:Use(ply)
	umsg.Start("sic_openpanel", ply)
	umsg.String(self.code .. ";" .. self.closetime .. ";" .. tostring(self.autoclose) .. ";" .. tostring(self.donotautoopen))
	umsg.End()
	ply.IrisCompEnt=self
end

function ENT:Touch(ent)
	if self.LockedGate == self.Entity then
		if ent:GetClass() == "stargate_sg1" or ent:GetClass() == "stargate_atlantis" or ent:GetClass() == "stargate_iris" then
			local gate, iris = self:FindGate()
			if iris ~= nil and gate ~= nil and gate:IsValid() and iris:IsValid() and iris:GetOwner() == self:GetOwner() then
				self.LockedGate = gate
				self.LockedIris = iris
				local ed = EffectData()
 					ed:SetEntity( self.Entity )
 				util.Effect( "propspawn", ed, true, true )
			end
		end
	end
end

function ENT:Think()
	local gate, iris
	if self.LockedGate == self.Entity then
		gate, iris = self:FindGate()
	else
		gate = self.LockedGate
		iris = self.LockedIris
	end
	if gate and iris then 
		if iris:GetOwner() == self:GetOwner() then
			if not gate.Outbound and (gate.IsOpen or gate.Dialling) then
				if self.autoclose and not self.didclose then
					if not iris.IsActivated then
						iris:Toggle()
						self.didclose = true	--We won't close the iris again until then next time the gate is active
					end
				end
			else
				self.wireCode = 0
				self.CodeStatus = 0
			end
		end
			
		if not (gate.IsOpen or gate.Dialling) and self.didclose and iris.IsActivated then
			self.didclose = false	--Resetting so we can autoclose again
			iris:Toggle()		--Make this optional in the future?
		end
		
		if self.didclose and not (gate.IsOpen or gate.Dialling) then
			self.didclose = false
		end
		
		if not (WireAddon == nil) then
			if gate.IsOpen or gate.Dialling then
				Wire_TriggerOutput(self.Entity, "Gate Active", 1)
				if not gate.Outbound then
					Wire_TriggerOutput(self.Entity, "Incoming Wormhole", 1)
				else
					Wire_TriggerOutput(self.Entity, "Incoming Wormhole", 0)
				end
			else
				Wire_TriggerOutput(self.Entity, "Gate Active", 0)
			end
			
			
			if self.donotautoopen and not gate.IsOpen then
				self.CodeStatus = 0
			end
			Wire_TriggerOutput(self.Entity, "Code Status", self.CodeStatus)
			
			Wire_TriggerOutput(self.Entity, "Received Code", self.wireCode)
		end
	end
	
	self.Entity:NextThink(CurTime()+0.5)
	return true
end

function ENT:TriggerInput(iname, value)
	local gate, iris
	if self.LockedGate == self.Entity then
		gate, iris = self:FindGate()
	else
		gate = self.LockedGate
		iris = self.LockedIris
	end
	if iname == "Iris Control" then
		iris:Toggle()
		if value == 0 and self.closetime ~= 0 then
			timer.Simple(self.closetime, AutoClose, self)
		end
	end
end

---------------------------------------------
-- Server/Client crossover stuff
---------------------------------------------

function ChangeIrisSettings(player, command, args)
	if player.IrisCompEnt and player.IrisCompEnt ~= NULL then
		player.IrisCompEnt.code = args[1]
		player.IrisCompEnt.closetime = tonumber(args[2])
		player.IrisCompEnt.autoclose = util.tobool(args[3])
		player.IrisCompEnt.donotautoopen = util.tobool(args[4])		
	end
end

concommand.Add("changeirissettings", ChangeIrisSettings)

function ToggleIris(player, command, args)
	if player.IrisCompEnt and player.IrisCompEnt ~= NULL then
		if player.IrisCompEnt.LockedGate == player.IrisCompEnt.Entity then
			_, iris = player.IrisCompEnt:FindGate()
		else
			 iris = player.IrisCompEnt.LockedIris
		end
		iris:Toggle()
	end
end

concommand.Add("togiris", ToggleIris)

---------------------------------------------
-- Gate Stuff
---------------------------------------------

function ENT:FindGate()  -- from aVoN's DHD
	local gate
	local iris
	local dist = 1000
	local pos = self.Entity:GetPos()
	for _,v in pairs(ents.FindByClass("stargate_*")) do
		if(v.IsStargate) then
			local sg_dist = (pos - v:GetPos()):Length()
			if(dist >= sg_dist) then
				dist = sg_dist
				gate = v
			end
		end
	end
	dist = 1000
	for _,v in pairs(ents.FindByClass("stargate_*")) do
		if(v.IsIris) then
			local i_dist = (pos - v:GetPos()):Length()
			if(dist >= i_dist) then
				dist = i_dist
				iris = v
			end
		end
	end
	return gate, iris
end


function ENT:RecieveIrisCode(code)
	local gate, iris
	if self.LockedGate == self.Entity then
		gate, iris = self:FindGate()
	else
		gate = self.LockedGate
		iris = self.LockedIris
	end
	local ret = 0
	self.wireCode = code
	if iris:GetOwner() == self:GetOwner() then
		local codeArray = string.Explode(",", self.code)
		for _,v in pairs(codeArray) do
			if code == tonumber(v) then
				if iris.IsActivated then
					if not self.donotautoopen then
						iris:Toggle()
						ret = 1
						if self.closetime ~= 0 then
							timer.Simple(self.closetime, AutoClose, self)
						end
					else
						ret = 2
						self.CodeStatus = 1
					end
				end
			end
		end
		if self.CodeStatus == 0 and self.donotautoopen then	-- if no code was found, this'll be 0 still
			self.CodeStatus = 2			-- so, that means the code was wrong
		end
	end
	return ret
end